package com.ruoyi.voucher.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.core.utils.bean.BeanUtils;
import com.ruoyi.system.api.RemoteAccountService;
import com.ruoyi.voucher.domain.Voucher;
import com.ruoyi.voucher.domain.VoucherAccessory;
import com.ruoyi.voucher.domain.VoucherDetails;
import com.ruoyi.voucher.domain.dto.TemplateSummarySubject;
import com.ruoyi.voucher.domain.vo.QueryVoucherVo;
import com.ruoyi.voucher.domain.dto.req.VoucherAccessoryReqDTO;
import com.ruoyi.voucher.domain.dto.req.VoucherDetailReqDTO;
import com.ruoyi.voucher.domain.dto.req.VoucherReqDTO;
import com.ruoyi.voucher.domain.dto.resp.VoucherRespDTO;
import com.ruoyi.voucher.mapper.VoucherAccessoryMapper;
import com.ruoyi.voucher.mapper.VoucherDetailsMapper;
import com.ruoyi.voucher.mapper.VoucherMapper;
import com.ruoyi.voucher.service.IVoucherService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestBody;

import javax.validation.Valid;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 凭证管理Service业务层处理
 * 
 * @author ruoyi
 * @date 2025-02-21
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class VoucherServiceImpl extends ServiceImpl<VoucherMapper,Voucher> implements IVoucherService
{

    private final VoucherMapper voucherMapper;

    private final VoucherDetailsMapper voucherDetailsMapper;

    private final RemoteAccountService accountService;

    private final VoucherAccessoryMapper voucherAccessoryMapper;

    private final VoucherAccessoryServiceImpl voucherAccessoryService;
    private final VoucherDetailsServiceImpl voucherDetailsService;

    /**
     * 查询凭证管理
     * 
     * @param id 凭证管理主键
     * @return 凭证管理
     */
    @Override
    public Voucher selectVoucherById(Long id) throws Exception {
        Voucher voucher = voucherMapper.selectVoucherByVoucherId(id);
        if (voucher == null){
            throw new Exception("当前数据有误");
        }
        List<VoucherDetails> details = voucherDetailsMapper.selectDetailsByVoucherId(voucher.getVoucherId());
        if (details != null){
            voucher.setDetails(details);
        }
        return voucher;
    }

    /**
     * 查询凭证管理列表
     * 
     * @param voucher 凭证管理
     * @return 凭证管理
     */
    @Override
    public List<Voucher> selectVoucherList(Voucher voucher)
    {
        return voucherMapper.selectVoucherList(voucher);
    }

    /**
     * 新增凭证管理
     * 
     * @param voucher 凭证管理
     * @return 结果
     */
    @Override
    public int insertVoucher(Voucher voucher)
    {
        return voucherMapper.insert(voucher);
    }

    /**
     * 修改凭证管理
     * 
     * @param voucherReqDTO 凭证管理
     * @return 结果
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int updateVoucher(VoucherReqDTO voucherReqDTO) throws Exception {
        if (voucherReqDTO == null || voucherReqDTO.getDetails() == null || voucherReqDTO.getDetails().isEmpty()) {
            throw new Exception("数据有误,修改失败");
        }
        try {
            Long accountId = accountService.getAccountId();
            Long voucherId = voucherReqDTO.getVoucherId();

            // 1. 更新凭证主表
            Voucher voucher = new Voucher();
            voucher.setVoucherId(voucherId);
            voucher.setWordId(voucherReqDTO.getWordId());
            voucher.setWordNo(voucherReqDTO.getWordNo());
            voucher.setVoucherDate(voucherReqDTO.getVoucherDate());
            voucher.setAccountPeriod(voucherReqDTO.getAccountPeriod());
            voucher.setAttachmentCount(voucherReqDTO.getAttachmentCount());
            voucher.setAccountSetsId(accountId);
            voucherMapper.updateById(voucher);

            // 2. 处理明细
            // 2.1 获取原有明细
            List<VoucherDetails> oldDetails = voucherDetailsService.list(
                    new LambdaQueryWrapper<VoucherDetails>()
                            .eq(VoucherDetails::getVoucherId, voucherId)
            );

            // 2.2 删除不再使用的明细
            if (!oldDetails.isEmpty()) {
                List<Long> oldDetailIds = oldDetails.stream()
                        .map(VoucherDetails::getId)
                        .collect(Collectors.toList());
                List<Long> newDetailIds = voucherReqDTO.getDetails().stream()
                        .map(VoucherDetailReqDTO::getId)
                        .filter(Objects::nonNull)
                        .collect(Collectors.toList());
                oldDetailIds.removeAll(newDetailIds);
                if (!oldDetailIds.isEmpty()) {
                    voucherDetailsService.removeByIds(oldDetailIds);
                }
            }

            // 2.3 更新或新增明细
            for (VoucherDetailReqDTO detail : voucherReqDTO.getDetails()) {
                VoucherDetails voucherDetails = new VoucherDetails();
                voucherDetails.setVoucherId(voucherId);
                voucherDetails.setSubjectId(detail.getSubjectId());
                voucherDetails.setSummaryId(detail.getSummaryId());
                voucherDetails.setCreditAmount(detail.getCreditAmount());
                voucherDetails.setDebitAmount(detail.getDebitAmount());

                if (detail.getId() != null) {
                    voucherDetails.setId(detail.getId());
                    voucherDetailsService.updateById(voucherDetails);
                } else {
                    voucherDetailsService.save(voucherDetails);
                }
            }

            // 3. 处理附件
            if (voucherReqDTO.getFileList() != null) {
                // 3.1 删除旧附件
                voucherAccessoryService.remove(
                        new LambdaQueryWrapper<VoucherAccessory>()
                                .eq(VoucherAccessory::getVoucherId, voucherId)
                );

                // 3.2 保存新附件
                for (VoucherAccessoryReqDTO accessoryReqDTO : voucherReqDTO.getFileList()) {
                    VoucherAccessory accessory = new VoucherAccessory();
                    accessory.setName(accessoryReqDTO.getAccessoryName());
                    accessory.setAccessoryUrl(accessoryReqDTO.getAccessoryUrl());
                    accessory.setVoucherId(voucherId);
                    voucherAccessoryService.save(accessory);
                }
            }

            return Math.toIntExact(voucherId);
        } catch (Exception e) {
            log.error("修改凭证失败", e);
            throw new Exception("修改凭证失败：" + e.getMessage());
        }
    }

    /**
     * 批量删除凭证管理
     * 
     * @param ids 需要删除的凭证管理主键
     * @return 结果
     */
    @Override
    public int deleteVoucherByIds(Long[] ids)
    {
        return voucherMapper.deleteVoucherByVoucherIds(ids);
    }

    /**
     * 删除凭证管理信息
     * 
     * @param id 凭证管理主键
     * @return 结果
     */
    @Override
    public int deleteVoucherById(Long id)
    {
        return voucherMapper.deleteVoucherByVoucherId(id);
    }

    /**
    * @Description: 新增凭证
    * @Param: [voucherReqDTO]
    * @return: int
    * @Author: Yuan
    */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int addVoucher(VoucherReqDTO voucherReqDTO) throws Exception {
        if (voucherReqDTO == null || voucherReqDTO.getDetails() == null || voucherReqDTO.getDetails().isEmpty()){
            throw new Exception("数据有误,新增失败");
        }
        Long accountId = accountService.getAccountId();
        Voucher voucher = new Voucher();
        voucher.setWordId(voucherReqDTO.getWordId());
        voucher.setWordNo(voucherReqDTO.getWordNo());
        voucher.setVoucherDate(voucherReqDTO.getVoucherDate());
        voucher.setAccountPeriod(voucherReqDTO.getAccountPeriod());
        voucher.setAttachmentCount(voucherReqDTO.getAttachmentCount());
        voucher.setAccountSetsId(accountId);
        try {
            voucherMapper.insert(voucher);
            Long voucherId = voucher.getVoucherId();
            List<VoucherDetailReqDTO> details = voucherReqDTO.getDetails();
            for (VoucherDetailReqDTO detail : details) {
                VoucherDetails voucherDetails = new VoucherDetails();
                voucherDetails.setVoucherId(voucherId);
                voucherDetails.setSubjectId(detail.getSubjectId());
                voucherDetails.setSummaryId(detail.getSummaryId());
                voucherDetails.setCreditAmount(detail.getCreditAmount());
                voucherDetails.setDebitAmount(detail.getDebitAmount());
                voucherDetailsMapper.insert(voucherDetails);
            }
            List<VoucherAccessoryReqDTO> accessoryList = voucherReqDTO.getFileList();
            if (accessoryList != null){
                for (VoucherAccessoryReqDTO accessoryReqDTO : accessoryList) {
                    VoucherAccessory accessory = new VoucherAccessory();
                    accessory.setName(accessoryReqDTO.getAccessoryName());
                    accessory.setAccessoryUrl(accessoryReqDTO.getAccessoryUrl());
                    accessory.setVoucherId(voucherId);
                    voucherAccessoryMapper.insert(accessory);
                }
            }
            return Math.toIntExact(voucherId);
        } catch (Exception e) {
            log.error("新增失败");
            throw new Exception(e);
        }
    }

    /**
    * @Description: 凭证列表
    * @Param: [queryVoucherDTO]
    * @return: java.util.List<com.ruoyi.voucher.domain.dto.resp.VoucherRespDTO>
    * @Author: Yuan
    */
    @Override
    public List<VoucherRespDTO> getVoucherList(QueryVoucherVo queryVoucherVo) {
        // 1. 设置账套ID
        try {
            queryVoucherVo.setAccountSetsId(accountService.getAccountId());

            // 2. 查询主表数据
            List<Voucher> vouchers = voucherMapper.getVoucherList(queryVoucherVo);
            if (vouchers.isEmpty()) {
                log.info("凭证列表数据为空");
                return Collections.emptyList();
            }

            // 3. 批量查询详情并分组
            List<Long> voucherIds = vouchers.stream()
                    .map(Voucher::getVoucherId)
                    .collect(Collectors.toList());
            Map<Long, List<TemplateSummarySubject>> detailsMap = voucherDetailsMapper.selectDetailsByVoucherIds(voucherIds)
                    .stream()
                    .collect(Collectors.groupingBy(TemplateSummarySubject::getVoucherId));

            // 4. 转换DTO
            return vouchers.stream()
                    .map(voucher -> {
                        VoucherRespDTO dto = new VoucherRespDTO();
                        BeanUtils.copyProperties(voucher, dto);
                        dto.setDetailId(voucher.getDetailId());
                        dto.setAuditName("admin");
                        dto.setDetails(detailsMap.getOrDefault(voucher.getVoucherId(), Collections.emptyList()));
                        return dto;
                    })
                    .collect(Collectors.toList());
        } catch (Exception e) {
            log.error("获取凭证列表失败");
            throw new RuntimeException(e);
        }
    }

    // 辅助方法
    private String resolveAuditName(Voucher voucher) {
        return switch (voucher.getAuditorId()) {
            case -1 -> "-1";
            case -2 -> "-2";
            default -> String.valueOf(voucher.getAuditorId());
        };
    }

    /**
    * @Description: 凭证列表
    * @Param: [queryVoucherVo]
    * @return: java.util.List<com.ruoyi.voucher.domain.Voucher>
    * @Author: Yuan
    */
    @Override
    public List<Voucher> selectVoucherList1(QueryVoucherVo queryVoucherVo){
        try {
            Long accountId = accountService.getAccountId();
            queryVoucherVo.setAccountSetsId(accountId);

            List<Voucher> voucherList = voucherMapper.selectVoucherList1(queryVoucherVo);
            if (voucherList.isEmpty()){
                log.error("凭证列表为空");
                return new ArrayList<>();
            }
            for (Voucher v : voucherList) {
                Long accessoryNum = voucherMapper.selectAccessoryNumByVoucherId(v.getVoucherId());
                List<VoucherDetails> details = voucherDetailsMapper.selectDetailsByVoucherId(v.getVoucherId());
                v.setDetails(details);
                v.setAccessoryNum(accessoryNum);
            }
            return voucherList;
        } catch (Exception e) {
            log.error("获取凭证列表失败");
            throw new RuntimeException(e);
        }

    }

}
